import { create } from 'zustand';
import { Cell, GameState } from '../types/game';
import { supabase } from '../lib/supabase';

const DIFFICULTIES = {
  easy: { rows: 9, cols: 9, mines: 10 },
  medium: { rows: 16, cols: 16, mines: 40 },
  hard: { rows: 16, cols: 30, mines: 99 },
};

interface GameStore extends GameState {
  initializeGame: (difficulty: 'easy' | 'medium' | 'hard') => void;
  revealCell: (row: number, col: number) => void;
  toggleFlag: (row: number, col: number) => void;
  saveScore: (playerName: string) => Promise<void>;
}

const createInitialGrid = (rows: number, cols: number): Cell[][] => {
  return Array(rows).fill(null).map((_, row) =>
    Array(cols).fill(null).map((_, col) => ({
      row,
      col,
      isMine: false,
      isRevealed: false,
      isFlagged: false,
      neighborMines: 0,
    }))
  );
};

const placeMines = (grid: Cell[][], mines: number, firstRow: number, firstCol: number) => {
  const rows = grid.length;
  const cols = grid[0].length;
  let minesPlaced = 0;
  
  // Create a safe zone around the first click
  const safeZone = [];
  for (let i = -1; i <= 1; i++) {
    for (let j = -1; j <= 1; j++) {
      const newRow = firstRow + i;
      const newCol = firstCol + j;
      if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols) {
        safeZone.push({ row: newRow, col: newCol });
      }
    }
  }

  while (minesPlaced < mines) {
    const row = Math.floor(Math.random() * rows);
    const col = Math.floor(Math.random() * cols);
    
    // Check if the position is in the safe zone
    const isSafe = safeZone.some(pos => pos.row === row && pos.col === col);
    
    if (!grid[row][col].isMine && !isSafe) {
      grid[row][col].isMine = true;
      minesPlaced++;
    }
  }

  // Calculate neighbor mines
  for (let row = 0; row < rows; row++) {
    for (let col = 0; col < cols; col++) {
      if (!grid[row][col].isMine) {
        let count = 0;
        for (let i = -1; i <= 1; i++) {
          for (let j = -1; j <= 1; j++) {
            if (row + i >= 0 && row + i < rows && col + j >= 0 && col + j < cols) {
              if (grid[row + i][col + j].isMine) count++;
            }
          }
        }
        grid[row][col].neighborMines = count;
      }
    }
  }

  return grid;
};

export const useGameStore = create<GameStore>((set, get) => ({
  grid: [],
  gameStatus: 'playing',
  difficulty: 'easy',
  timeElapsed: 0,
  minesCount: DIFFICULTIES.easy.mines,
  isFirstClick: true,

  initializeGame: (difficulty) => {
    const { rows, cols, mines } = DIFFICULTIES[difficulty];
    set({
      grid: createInitialGrid(rows, cols),
      gameStatus: 'playing',
      difficulty,
      timeElapsed: 0,
      minesCount: mines,
      isFirstClick: true,
    });
  },

  revealCell: (row, col) => {
    const state = get();
    const { grid, gameStatus, isFirstClick, difficulty } = state;
    if (gameStatus !== 'playing' || grid[row][col].isRevealed || grid[row][col].isFlagged) return;

    let newGrid = [...grid];

    // Handle first click
    if (isFirstClick) {
      const { mines } = DIFFICULTIES[difficulty];
      newGrid = placeMines(newGrid, mines, row, col);
      set({ isFirstClick: false });
    }

    const revealRecursive = (r: number, c: number) => {
      if (r < 0 || r >= grid.length || c < 0 || c >= grid[0].length) return;
      if (newGrid[r][c].isRevealed || newGrid[r][c].isFlagged) return;

      newGrid[r][c].isRevealed = true;
      if (newGrid[r][c].neighborMines === 0 && !newGrid[r][c].isMine) {
        for (let i = -1; i <= 1; i++) {
          for (let j = -1; j <= 1; j++) {
            revealRecursive(r + i, c + j);
          }
        }
      }
    };

    if (newGrid[row][col].isMine) {
      // Reveal all mines when game is lost
      newGrid.forEach(row => row.forEach(cell => {
        if (cell.isMine) cell.isRevealed = true;
      }));
      set({ gameStatus: 'lost', grid: newGrid });
    } else {
      revealRecursive(row, col);
      
      // Check for win condition
      const hasWon = newGrid.every(row => 
        row.every(cell => 
          (cell.isMine && !cell.isRevealed) || (!cell.isMine && cell.isRevealed)
        )
      );
      
      if (hasWon) {
        set({ gameStatus: 'won', grid: newGrid });
      } else {
        set({ grid: newGrid });
      }
    }
  },

  toggleFlag: (row, col) => {
    const { grid, gameStatus } = get();
    if (gameStatus !== 'playing' || grid[row][col].isRevealed) return;

    const newGrid = [...grid];
    newGrid[row][col].isFlagged = !newGrid[row][col].isFlagged;
    set({ grid: newGrid });
  },

  saveScore: async (playerName) => {
    const { timeElapsed, difficulty } = get();
    try {
      const { error } = await supabase
        .from('scores')
        .insert([
          {
            player_name: playerName,
            difficulty,
            time: timeElapsed,
          },
        ]);

      if (error) throw error;
    } catch (error) {
      console.error('Error saving score:', error);
      throw error;
    }
  },
}));